/**
 * Copyright (C) 2011 Andrew C. Love (DNC) <dnc.app.sup@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dnc.cloak.framework.security.encryption;

import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

import org.apache.log4j.Logger;

import com.dnc.cloak.framework.context.Context;
import com.dnc.cloak.framework.security.encryption.KeyContext.KeyStoreSource;
import com.dnc.cloak.framework.service.ServiceException;
import com.dnc.cloak.framework.spring.SpringIntegration;
import com.dnc.cloak.service.EncryptionService;

public class EncryptionHelper {
	private static final Logger logger = Logger.getLogger(EncryptionHelper.class.getName());

    public static String encryptSymmetric(Context context, String keyStoreName, KeyStoreSource keyStoreSource, String confidentialData) throws EncryptionException {
    	try {
			logger.debug("encryptSymmetric");
			
			KeyContext keyContext = new KeyContext();        
			keyContext.setKeystoreName(keyStoreName);
			keyContext.setKeystoreSource(keyStoreSource);
			keyContext.setSymmetricEncryptionMode();
			
			EncryptionService service = (EncryptionService)SpringIntegration.context.getBean("encryptionService");

			keyContext = service.getSymmetricKey(context, keyContext);
			EncryptedData encryptedData = service.encryptSymmetric(context,keyContext, new ConfidentialData(confidentialData));

			String encoded = EncryptionUtil.base64Encode(encryptedData.getData());
			
			return encoded;
		} 
    	catch (ServiceException ex) {
			throw new EncryptionException(ex);
		}        
    }

    public static String decryptSymmetric(Context context, String keyStoreName, KeyStoreSource keyStoreSource, String encryptedData) throws EncryptionException {
    	try {
			logger.debug("decryptSymmetric");

			KeyContext keyContext = new KeyContext();
			keyContext.setKeystoreName(keyStoreName);
			keyContext.setKeystoreSource(keyStoreSource);
			keyContext.setSymmetricEncryptionMode();
			
			byte[] decodedBytes = EncryptionUtil.base64Decode(encryptedData);
            EncryptionService service = (EncryptionService)SpringIntegration.context.getBean("encryptionService");
			keyContext = service.getSymmetricKey(context, keyContext);
			
			ConfidentialData confidentialData = service.decryptSymmetric(context,keyContext, new EncryptedData(decodedBytes));

			return new String(confidentialData.getData());
		} 
    	catch (ServiceException ex) {
			throw new EncryptionException(ex);
		}        
    }


    public static String encryptAsymmetric(Context context, String keyStoreName, KeyStoreSource keyStoreSource, String confidentialData) throws EncryptionException {
    	try {
			logger.debug("encryptAsymmetric");

			KeyContext keyContext = new KeyContext();
			keyContext.setKeystoreName(keyStoreName);
			keyContext.setKeystoreSource(keyStoreSource);
			keyContext.setAsymmetricEncryptionMode();
			
            EncryptionService service = (EncryptionService)SpringIntegration.context.getBean("encryptionService");
			keyContext = service.getPublicKey(context, keyContext);
			EncryptedData encryptedData = service.encryptAsymmetric(context,keyContext, new ConfidentialData(confidentialData));

			String encoded = EncryptionUtil.base64Encode(encryptedData.getData());
			return encoded;
		} 
    	catch (ServiceException ex) {
			throw new EncryptionException(ex);
		}        
    }

    public static String decryptAsymmetric(Context context, String keyStoreName, KeyStoreSource keyStoreSource, String encryptedData) throws EncryptionException {
    	try {
			logger.debug("decryptAsymmetric");

			KeyContext keyContext = new KeyContext();
			keyContext.setKeystoreName(keyStoreName);
			keyContext.setKeystoreSource(keyStoreSource);
			keyContext.setSymmetricEncryptionMode();
			
			byte[] decodedBytes = EncryptionUtil.base64Decode(encryptedData);
            EncryptionService service = (EncryptionService)SpringIntegration.context.getBean("encryptionService");
			keyContext = service.getPrivateKey(context, keyContext);
			
			ConfidentialData confidentialData = service.decryptAsymmetric(context,keyContext, new EncryptedData(decodedBytes));

			return new String(confidentialData.getData());
		} 
    	catch (ServiceException ex) {
			throw new EncryptionException(ex);
		}        
    }
    
    public static Certificate getCertificate(Context context, String keyStoreName, KeyStoreSource keyStoreSource) throws EncryptionException {
    	try {
			logger.debug("getCertificate");

			KeyContext keyContext = new KeyContext();
			keyContext.setKeystoreName(keyStoreName);
			keyContext.setKeystoreSource(keyStoreSource);
			keyContext.setAsymmetricEncryptionMode();
			
            EncryptionService service = (EncryptionService)SpringIntegration.context.getBean("encryptionService");
			keyContext = service.getCertificate(context, keyContext);
			
			return keyContext.getCertificate();
		} 
    	catch (ServiceException ex) {
			throw new EncryptionException(ex);
		}        
    }
    
    public static X509Certificate getX509Certificate(Context context, String keyStoreName, KeyStoreSource keyStoreSource) throws EncryptionException  {
    	try {
			logger.debug("getX509Certificate");

			KeyContext keyContext = new KeyContext();
			keyContext.setKeystoreName(keyStoreName);
			keyContext.setAsymmetricEncryptionMode();
			
            EncryptionService service = (EncryptionService)SpringIntegration.context.getBean("encryptionService");
			keyContext = service.getCertificate(context, keyContext);
			
			return (X509Certificate)keyContext.getCertificate();
		} 
    	catch (ServiceException ex) {
			throw new EncryptionException(ex);
		}        
    }

    public static String encryptSessionKey(Context context, String keyStoreName, KeyStoreSource keyStoreSource, String confidentialData) throws EncryptionException {
       	try {
			logger.debug("encryptSessionKey");

			KeyContext keyContext = new KeyContext();
			keyContext.setKeystoreName(keyStoreName);
			keyContext.setKeystoreSource(keyStoreSource);
			keyContext.setAsymmetricEncryptionMode();
			
            EncryptionService service = (EncryptionService)SpringIntegration.context.getBean("encryptionService");
			EncryptedData encryptedData = service.encryptSessionKey(context,keyContext, new ConfidentialData(confidentialData));

			String encoded = EncryptionUtil.base64Encode(encryptedData.getData());
			return encoded;
		} 
    	catch (ServiceException ex) {
			throw new EncryptionException(ex);
		}        
     }

    public static String decryptSessionKey(Context context, String keyStoreName, KeyStoreSource keyStoreSource, String encryptedData) throws EncryptionException {
     	try {
			logger.debug("decryptSessionKey");
			
			KeyContext keyContext = new KeyContext();
			keyContext.setKeystoreName(keyStoreName);
			keyContext.setKeystoreSource(keyStoreSource);
			keyContext.setSymmetricEncryptionMode();
			
			byte[] decodedBytes = EncryptionUtil.base64Decode(encryptedData);
            EncryptionService service = (EncryptionService)SpringIntegration.context.getBean("encryptionService");
			keyContext = service.getPrivateKey(context, keyContext);
			
			ConfidentialData confidentialData = service.decryptSessionKey(context,keyContext, new EncryptedData(decodedBytes));

			return new String(confidentialData.getData());
		} 
    	catch (ServiceException ex) {
			throw new EncryptionException(ex);
		}        
   }
}
